#######这一模块改自别人代码。
#######主要计算了和紧急联系人相关的特征。
#######主要通过DataFrame数据结构来实现。
import datetime
import os
import re
from copy import deepcopy
import numpy as np
import pandas as pd

def get_root_dir(path):
    path_list=path.split(os.path.sep)
    index=path_list.index("featurelib")
    return os.path.sep.join(path_list[:index+1])

class CallUnBase0V1Module4():
    def __init__(self):
        cur_path=(os.path.abspath('.'))
        root_path=get_root_dir(cur_path)
        path=os.path.join(root_path,'feature_conf', 'call','un','call_un_base0_v1', 'call_un_base0_v1_module4.featlist')
        self.res_map={k.strip().split('|')[0].strip():'None' for k in open(path,encoding='utf-8')}
    def main(self,data):
        self.gen_context(data)
        res_map=self.extract_feature()
        return res_map    

    def gen_context(self, data=None):
        contact_phone_list=data['contact_phone_list']
        clean_call_list = []
        for call in data['call_list']:
            if call['phone'] not in contact_phone_list:
                continue
            clean_call_list.append(call)
        data['call_list'] = deepcopy(clean_call_list)
        self.data=deepcopy(data)


    def extract_feature(self):
        res_map=deepcopy(self.res_map)
        raw_df = pd.DataFrame(self.data['call_list'])
        # base类已经做完回溯逻辑
        if raw_df.shape[0] == 0:
            return res_map
        raw_df = raw_df[raw_df['diff_days'] <= 180]

        raw_df['call_dt'] = raw_df['calltime'].map(datetime.datetime.date)
        raw_df['period_flag'] = raw_df['calltime'].map(lambda x: self.caculate_hour(str(x)[11:13]))

        raw_df['type_flag'] = raw_df['type'].map(lambda x: str(x) if str(x) in ['1', '2'] else 'other')
        raw_df['all_flag'] = ''
        raw_df['duration'][raw_df.duration < 0] = 0
        raw_df['duration_flag'] = raw_df['duration'].map(lambda x: '0' if x <= 0 else '1' if x < 60 else '2')
        raw_df = raw_df.sort_values(by=['calltime','phone'], ascending=True)

        type_list = ['all_flag', 'type_flag', 'duration_flag']
        days_list = {'all': '_all', 90: '_3m', 30: '_1m', 7: "_7d"}
        for window in days_list.keys():

            suffix_name = days_list[window]
            if window == 'all':
                windows_df = raw_df
            else:
                windows_df = raw_df[raw_df["diff_days"] <= window]

            for index in range(len(type_list)):
                if index == 0:
                    col2_list = type_list
                else:
                    col2_list = type_list[index + 1 :]
                col1 = type_list[index]
                col_name1 = col1.split('_')[0]
                for value1 in windows_df[col1].unique():
                    value1_df = windows_df[windows_df[col1] == value1]
                    if value1_df.shape[0] > 0:
                        for col2 in col2_list:
                            col_name2 = col2.split('_')[0]
                            for value2 in value1_df[col2].unique():
                                value2_df = value1_df[value1_df[col2] == value2]
                                if value2_df.shape[0] > 0:
                                    col_name = 'call_' + col_name1 + value1 + '_' + col_name2 + value2
                                    if 'typeother' in col_name and 'duration1' in col_name:
                                        continue
                                    if 'typeother' in col_name and 'duration2' in col_name:
                                        continue
                                    col_name = 'econtact_call_' + col_name1 + value1 + '_' + col_name2 + value2
                                    res_map[col_name + '_cnt_ph' + suffix_name] = (
                                        value2_df[['duration', 'phone']].groupby('phone').count().max()['duration']
                                    )
                                    res_map[col_name + '_duration_max_ph' + suffix_name] = (
                                        value2_df[['duration', 'phone']].groupby('phone').sum().max()['duration']
                                    )
                                    res_map[col_name + '_cnt' + suffix_name] = value2_df.shape[0]
                                    res_map[col_name + '_dis_cnt' + suffix_name] = len(value2_df['phone'].unique())
                                    value2_df['call_dt_shift'] = value2_df['call_dt'].shift(1)
                                    value2_df['call_days_gap'] = (
                                        (value2_df['call_dt'] - value2_df['call_dt_shift']).map(lambda x:pd.NA if pd.isna(x) else x.days)
                                    )
                                    res_map[col_name + '_day_gap_max' + suffix_name] = value2_df['call_days_gap'].max()
                                    res_map[col_name + '_day_gap_avg' + suffix_name] = value2_df['call_days_gap'].mean()
                                    if 'duration0' not in col_name and 'typeother' not in col_name:
                                        res_map[col_name + '_duration_max' + suffix_name] = value2_df['duration'].max()
                                        res_map[col_name + '_duration_avg' + suffix_name] = value2_df['duration'].mean()
                                        res_map[col_name + '_duration_sum' + suffix_name] = value2_df['duration'].sum()

        return res_map

    def caculate_hour(self, hour):
        hour = int(hour)
        if hour >= 6 and hour < 9:
            return '6_9'
        elif hour >= 9 and hour < 12:
            return '9_12'
        elif hour >= 12 and hour < 14:
            return '12_14'
        elif hour >= 14 and hour < 17:
            return '14_17'
        elif hour >= 17 and hour < 20:
            return '17_20'
        elif hour >= 20 and hour < 23:
            return '20_23'
        else:
            return '23_6'
